-module(parser).
%-compile([native]).
-export([
         test/0,
	 parse/1
        ]).

parse_smoosh(Parsed, [{{keyword, kw_mkay}, _}|Terms]) when is_list(Parsed) -> {Parsed, Terms};
parse_smoosh(Parsed, [{{keyword, kw_an}, _}|Terms]) when is_list(Parsed) ->
    {Exp, Left} = parse_expression(Terms),
    parse_smoosh(Parsed ++ [Exp], Left);
parse_smoosh(Parsed, Terms) when is_list(Terms), is_list(Parsed) ->
    {Exp, Left} = parse_expression(Terms),
    parse_smoosh(Parsed ++ [Exp], Left).

drop_optional_an([{{keyword, kw_an}, _}|Terms]) -> Terms;
drop_optional_an(Terms) when is_list(Terms) -> Terms.

parse_expression_nobukkit([{{numbr, _}=Term, _}|Terms]) -> {Term, Terms};
parse_expression_nobukkit([{{numbar, _}=Term, _}|Terms]) -> {Term, Terms};
parse_expression_nobukkit([{{yarn, _}=Term, _}|Terms]) -> {Term, Terms};
parse_expression_nobukkit([{{noob, _}=Term, _}|Terms]) -> {Term, Terms};
parse_expression_nobukkit([{{troof, _}=Term, _}|Terms]) -> {Term, Terms};
parse_expression_nobukkit([{{identifier, _}=Term, _}|Terms]) -> {Term, Terms};
parse_expression_nobukkit([{{keyword, kw_smoosh}, _}|Terms]) -> parse_smoosh([], Terms);
parse_expression_nobukkit([{{binary_math_op, Op}, _}, {{keyword, kw_of}, _}|Terms]) ->
    {Exp1, Left1} = parse_expression(Terms),
    [{{keyword, kw_an}, _}|Left2] = Left1,
    {Exp2, Left3} = parse_expression(Left2),
    {{binary_math_op, Op, Exp1, Exp2}, Left3};
parse_expression_nobukkit([{{binary_logic_op, Op}, _}, {{keyword, kw_of}, _}|Terms]) ->
    {Exp1, Left1} = parse_expression(Terms),
    Left2 = drop_optional_an(Left1),
    {Exp2, Left3} = parse_expression(Left2),
    {{binary_logic_op, Op, Exp1, Exp2}, Left3};
parse_expression_nobukkit([{{binary_op, kw_both}, _}, {{keyword, kw_of}, _}|Terms]) ->
    {Exp1, Left1} = parse_expression(Terms),
    Left2 = drop_optional_an(Left1),
    {Exp2, Left3} = parse_expression(Left2),
    {{binary_logic_op, kw_both, Exp1, Exp2}, Left3};
parse_expression_nobukkit([{{binary_op, kw_both}, _}, {{keyword, kw_saem}, _}|Terms]) ->
    {Exp1, Left1} = parse_expression(Terms),
    Left2 = drop_optional_an(Left1),
    {Exp2, Left3} = parse_expression(Left2),
    {{binary_compare_op, kw_both, Exp1, Exp2}, Left3};
parse_expression_nobukkit([{{binary_compare_op, kw_diffrint}, _}|Terms]) ->
    {Exp1, Left1} = parse_expression(Terms),
    Left2 = drop_optional_an(Left1),
    {Exp2, Left3} = parse_expression(Left2),
    {{binary_compare_op, kw_diffrint, Exp1, Exp2}, Left3};
parse_expression_nobukkit([{{unary_op, kw_not}, _}|Terms]) ->
    {Exp, Left} = parse_expression(Terms),
    {{unary_op, kw_not, Exp}, Left};
parse_expression_nobukkit([{{keyword, kw_maek}, _} | Terms]) ->
    {Exp, [First|Left1]} = parse_expression(Terms),
    case First of
        {{keyword, kw_a}, _} ->
            [{{type, _}=Type, _}|Left2] = Left1,
            {{cast, Exp, Type}, Left2};
        {{type, _}=Type, _} ->
            {{cast, Exp, Type}, Left1}
    end;
parse_expression_nobukkit([{{keyword, KWord}, Pos} | _]) ->
	Msg = "Unexpected keyword ~p at ~p, expecting expression (no bukkit)",
	Args = [KWord, Pos],
	throw({parser_error, lists:flatten(io_lib:format(Msg, Args))}).

parse_expression(Terms) ->
    case parse_expression_nobukkit(Terms) of
        {KeyExp, [{{keyword, kw_in}, _}, {{keyword, kw_mah}, _} | Left1]} ->
            case parse_expression(Left1) of
                {{bukkit_selector, BukkitName, Key}, Left2} ->
                    {{bukkit_selector, BukkitName, Key++[KeyExp]}, Left2};
                {BukkitNameExp, Left2} ->
                    {{bukkit_selector, BukkitNameExp, [KeyExp]}, Left2}
            end;
        Res -> Res
    end.

%%%

parse_visible(Parsed, [{separator, _} | _] = Terms) when is_list(Parsed) ->
    {Parsed, Terms};
parse_visible(Parsed, [{exclamation, _} | Terms]) when is_list(Parsed) ->
    {Parsed ++ [{yarn, "\n"}], Terms};
parse_visible(Parsed, Terms) when is_list(Parsed), is_list(Terms) ->
    {Expression, Left} = parse_expression(Terms),
    parse_visible(Parsed ++ [Expression], Left).

%%%

parse_ya_block_cont(Parsed, [{{keyword,kw_mebbe}, _}|_] = Terms) when is_list(Parsed) ->
    {Parsed, Terms};
parse_ya_block_cont(Parsed, [{{keyword,kw_no}, _},{{keyword,kw_wai}, _}|_] = Terms) when is_list(Parsed) ->
    {Parsed, Terms};
parse_ya_block_cont(Parsed, [{{keyword,kw_oic}, _}|_] = Terms) when is_list(Parsed) ->
    {Parsed, Terms};
parse_ya_block_cont(Parsed, Terms) when is_list(Parsed), is_list(Terms) ->
    {Stmt, [{separator, _}|Left]} = parse_statement(Terms),
    parse_ya_block_cont(Parsed ++ [Stmt], Left).

parse_ya_block([{{keyword, kw_ya}, _}, {{keyword, kw_rly}, _}, {separator, _} | Terms]) -> 
    parse_ya_block_cont([], Terms).
%parse_ya_block(Terms) when is_list(Terms) -> 
%    {undefined, Terms}. % Spec says - it's needed

parse_no_block_cont(Parsed, [{{keyword,kw_oic}, _}|_] = Terms) when is_list(Parsed) ->
    {Parsed, Terms};
parse_no_block_cont(Parsed, Terms) when is_list(Parsed), is_list(Terms) ->
    {Stmt, [{separator, _}|Left]} = parse_statement(Terms),
    parse_no_block_cont(Parsed ++ [Stmt], Left).

parse_no_block([{{keyword, kw_no}, _}, {{keyword, kw_wai}, _}, {separator, _} | Terms]) -> 
    parse_no_block_cont([], Terms);
parse_no_block(Terms) when is_list(Terms) -> 
    {[], Terms}.

parse_mebbe_block_cont(Parsed, [{{keyword, kw_no}, _}, {{keyword, kw_wai}, _}|_] = Terms) when is_list(Parsed) ->
    {Parsed, Terms};
parse_mebbe_block_cont(Parsed, [{{keyword, kw_oic}, _}|_] = Terms) when is_list(Parsed) ->
    {Parsed, Terms};
parse_mebbe_block_cont(Parsed, [{{keyword, kw_mebbe}, _}|_] = Terms) when is_list(Parsed) ->
    {Parsed, Terms};
parse_mebbe_block_cont(Parsed, Terms) when is_list(Parsed), is_list(Terms) ->
    {Stmt, [{separator, _}|Left]} = parse_statement(Terms),
    parse_mebbe_block_cont(Parsed ++ [Stmt], Left).

parse_mebbe_block(Terms) when is_list(Terms) ->
    {Exp, [{separator, _} | Left1]} = parse_expression(Terms),
    {Block, Left2} = parse_mebbe_block_cont([], Left1),
    {{Exp, Block}, Left2}.

parse_mebbe_blocks(MebbeBlocks, [{{keyword, kw_mebbe}, _} | Terms]) when is_list(MebbeBlocks) ->
    {MebbeBlock, Left} = parse_mebbe_block(Terms),
    parse_mebbe_blocks(MebbeBlocks ++ [MebbeBlock], Left);
parse_mebbe_blocks(MebbeBlocks, Terms) when is_list(Terms), is_list(MebbeBlocks) ->
    {MebbeBlocks, Terms}.
%%%

parse_conditional(Terms) when is_list(Terms) -> 
    {YaBlock, Left1} = parse_ya_block(Terms),
    {MebbeBlocks, Left2} = parse_mebbe_blocks([], Left1),
    {NoBlock, Left3} = parse_no_block(Left2),
    [{{keyword, kw_oic}, _} | Other] = Left3,
    {{YaBlock, NoBlock, MebbeBlocks}, Other}.

%%%

parse_switch_block(Parsed, [{{keyword, kw_oic}, _}|_]=Terms) ->
    {Parsed, Terms};
parse_switch_block(Parsed, [{{keyword, kw_omgwtf}, _}|_]=Terms) ->
    {Parsed, Terms};
parse_switch_block(Parsed, [{{keyword, kw_omg}, _}|_]=Terms) ->
    {Parsed, Terms};
parse_switch_block(Parsed, Terms) ->
    {Stmt, [{separator, _}|Left]} = parse_statement(Terms),
    parse_switch_block(Parsed ++ [Stmt], Left).

parse_switch(Parsed, [{{keyword, kw_oic}, _} | Terms]) when is_list(Parsed) ->
    {Parsed, Terms};
parse_switch(Parsed, [{{keyword, kw_omg}, _} | Terms]) when is_list(Parsed) ->
    {Exp, [{separator, _}|Left1]} = parse_expression(Terms),
    {Block, Left2} = parse_switch_block([], Left1),
    parse_switch(Parsed ++ [{Exp, Block}], Left2);
parse_switch(Parsed, [{{keyword, kw_omgwtf}, _}, {separator, _} | Terms]) when is_list(Parsed) ->
    {Block, [{{keyword, kw_oic}, _}|Left1]} = parse_switch_block([], Terms),
    {Parsed ++ [{catchall, Block}], Left1}.
    

parse_switch(Terms) when is_list(Terms) ->
    parse_switch([], Terms).

%%%

parse_loop_block(Parsed, [{{keyword, kw_im}, _}, {{keyword, kw_outta}, _}, {{keyword, kw_yr}, _}, {{identifier, _}, _}|Terms]) when is_list(Parsed) ->
    {Parsed, Terms};
parse_loop_block(Parsed, [{separator, _}|Terms]) when is_list(Parsed) ->
    parse_loop_block(Parsed, Terms);
parse_loop_block(Parsed, Terms) when is_list(Parsed),is_list(Terms) ->
    {Result, [{separator, _}|Other]} = parse_statement(Terms),
    parse_loop_block(Parsed ++ [Result], Other).

parse_loop(Terms) when is_list(Terms) -> 
    parse_loop_block([], Terms).

%%%

parse_statement([{{buildin, visible}, _} | Terms]) ->
    {Expressions, Left} = parse_visible([], Terms),
    {{visible, Expressions}, Left};
parse_statement([{{buildin, gimmeh}, _} | Terms]) ->
    {Expression, Left} = parse_expression(Terms),
    {{gimmeh, Expression}, Left};
parse_statement([{{keyword, kw_im}, _}, {{keyword, kw_in}, _}, {{keyword, kw_yr}, _}, {{identifier, _}, _}, {separator, _} | Terms]) ->
    {Instructions, Left} = parse_loop(Terms),
    {{loop, Instructions}, Left};
parse_statement([{{keyword, kw_o}, _}, {{keyword, kw_rlyq}, _}, {separator, _} | Terms]) ->
    {Choices, Left} = parse_conditional(Terms),
    {{condition, Choices}, Left};
parse_statement([{{keyword, kw_wtfq}, _}, {separator, _} | Terms]) ->
    {Cases, Left} = parse_switch(Terms),
    {{switch, Cases}, Left};
parse_statement([{{keyword, kw_i}, _}, {{keyword, kw_has}, _}, {{keyword, kw_a}, _},
        {{identifier, Var}, _}, {{keyword, kw_itz}, _} | Terms]) ->
    {Expression, Left} = parse_expression(Terms),
    {{assignment_new, Var, Expression}, Left};
parse_statement([{{keyword, kw_i}, _}, {{keyword, kw_has}, _}, {{keyword, kw_a}, _},
        {{identifier, Var}, _} | Terms]) ->
    {{assignment_new, Var, {noob,noob}}, Terms};
parse_statement([{bukkit_selector, _Name, _Sel}=Var, {{keyword, kw_r}, _} | Terms]) ->
    {Exp, Left} = parse_expression(Terms),
    {{assignment, Var, Exp}, Left};
parse_statement([{Var, {_Row,_Col}}, {{keyword, kw_r}, _} | Terms]) ->
    {Exp, Left} = parse_expression(Terms),
    {{assignment, Var, Exp}, Left};
parse_statement([{{keyword, kw_gtfo}, _} | Terms]) ->
    {{gtfo}, Terms};
parse_statement([{{identifier, _}=Var, _}, {{keyword, kw_is}, _}, {{keyword, kw_now}, _}, {{keyword, kw_a}, _}, {{type, _}=Type, _} | Terms]) ->
    {{cast_inplace, Var, Type}, Terms};
parse_statement(Terms) ->
    case parse_expression(Terms) of
        {{bukkit_selector, _, _}=Exp, Left} -> parse_statement([Exp]++Left);
        {Exp, Left} -> {{expression, Exp}, Left}
    end.

%%%

parse_function(_Terms) -> [].

%%%

parse_main_block(Parsed, [{{keyword, kw_kthxbye}, _}|_]) when is_list(Parsed) ->
    {Parsed, []};
parse_main_block(Parsed, [{separator, _}|Terms]) when is_list(Parsed) ->
    parse_main_block(Parsed, Terms);
parse_main_block(Parsed, [{{keyword, kw_how}, _},{{keyword, kw_duz}, _},{{keyword, kw_i}, _},{{identifier, _Name}, _}|Terms]) when is_list(Parsed),is_list(Terms) ->
    case parse_function(Terms) of
		{Result, [{separator, _}|Other]} -> parse_main_block(Parsed ++ [Result], Other);
		_ -> throw({parser_error, "functions - not supported"})
	end;
parse_main_block(Parsed, Terms) when is_list(Parsed),is_list(Terms) ->
    case parse_statement(Terms) of
		{_Result, [{separator, _}]} ->
			 {Last, Pos} = lists:last(Terms),
			 Msg = "Unexpected EOF after ~p at ~p, expecting KTHXBYE or statement",
			 Args = [Last, Pos],
			 throw({parser_error, lists:flatten(io_lib:format(Msg, Args))});
		{Result, [{separator, _}|Other]} -> parse_main_block(Parsed ++ [Result], Other);
		{_Result, [{Next, Pos}|_Other]} -> 
			 Msg = "Unexpected ~p at ~p, expecting separator",
			 Args = [Next, Pos],
			 throw({parser_error, lists:flatten(io_lib:format(Msg, Args))});
		{_Result, []} -> 
			 {Last, Pos} = lists:last(Terms),
			 Msg = "Expected separator after ~p at ~p, got EOF",
			 Args = [Last, Pos],
			 throw({parser_error, lists:flatten(io_lib:format(Msg, Args))})
	end.

%%%

parse(Parsed, [{{keyword, kw_hai}, _}, {separator, _} | Terms]) when is_list(Parsed) ->
    {Result, Left} = parse_main_block([], Terms),
    parse(Parsed ++ Result, Left);
parse(Parsed, []) when is_list(Parsed) -> Parsed.

parse(Terms) -> parse([], Terms).

%%%%%%%%%%%%%%%%%%

test_set() -> [
    {fun(A) -> parse_main_block([], scanner:scan(A)) end,
        "I HAS A var , KTHXBYE",
        {[{assignment_new, "var", {noob,noob}}], []}},
    {fun(A) -> parse_main_block([], scanner:scan(A)) end,
        "I HAS A var , I HAS A var , KTHXBYE",
        {[{assignment_new, "var", {noob,noob}},{assignment_new, "var", {noob,noob}}], []}},
    {fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, I HAS A var ITZ 2, KTHXBYE",
        [{assignment_new, "var", {numbr,2}}]},
    {fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, I HAS A var, KTHXBYE",
        [{assignment_new, "var", {noob,noob}}]},
    {fun(A) -> parse_expression(scanner:scan(A)) end,
        "SUM OF 2 AN 3,",
        {{binary_math_op, kw_sum, {numbr,2}, {numbr,3}},[{separator, {0,13}}]}},
    {fun(A) -> parse_expression(scanner:scan(A)) end,
        "SUM OF 2 AN DIFF OF 3 AN a,",
        {{binary_math_op, kw_sum, {numbr,2}, {binary_math_op, kw_diff, {numbr,3}, {identifier,"a"}}},[{separator, {0,26}}]}},
    {fun(A) -> parse_expression(scanner:scan(A)) end,
        "BOTH OF WIN AN 1,",
        {{binary_logic_op, kw_both, {troof,win}, {numbr,1}},[{separator, {0,16}}]}},
    {fun(A) -> parse_expression(scanner:scan(A)) end,
        "BOTH OF WIN 1,",
        {{binary_logic_op, kw_both, {troof,win}, {numbr,1}},[{separator, {0,13}}]}},
    {fun(A) -> parse_expression(scanner:scan(A)) end,
        "WON OF WIN AN 1,",
        {{binary_logic_op, kw_won, {troof,win}, {numbr,1}},[{separator, {0,15}}]}},
    {fun(A) -> parse_expression(scanner:scan(A)) end,
        "BOTH SAEM WIN AN 1,",
        {{binary_compare_op, kw_both, {troof,win}, {numbr,1}},[{separator, {0,18}}]}},
    {fun(A) -> parse_expression(scanner:scan(A)) end,
        "1 IN MAH bukkit,",
        {{bukkit_selector, {identifier, "bukkit"}, [{numbr,1}]},[{separator, {0,15}}]}},
    {fun(A) -> parse_statement(scanner:scan(A)) end,
        "I HAS A wabbit ITZ \"animal\" IN MAH bukkit,",
        {{assignment_new, "wabbit",
            {bukkit_selector, {identifier, "bukkit"}, [{yarn,"animal"}]}},
            [{separator, {0,41}}]}},
    {fun(A) -> parse_statement(scanner:scan(A)) end,
        "\"animal\" IN MAH bukkit R wabbit,",
        {{assignment,
            {bukkit_selector, {identifier, "bukkit"}, [{yarn,"animal"}]},
            {identifier, "wabbit"}},
            [{separator, {0,31}}]}},
    {fun(A) -> parse_expression(scanner:scan(A)) end,
        "\"x\" IN MAH 1 IN MAH bukkit,",
        {{bukkit_selector, {identifier, "bukkit"}, [{numbr,1},{yarn,"x"}]},[{separator, {0,26}}]}},
    {fun(A) -> parse_smoosh([], scanner:scan(A)) end,
        "\"abc\" AN \"def\" SUM OF 1 AN 2 MKAY ,",
        {[{yarn, "abc"}, {yarn, "def"}, {binary_math_op, kw_sum, {numbr,1}, {numbr,2}}],[{separator, {0,34}}]}},
    {fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI , var R 3, KTHXBYE",
        [{assignment, {identifier, "var"}, {numbr,3}}]},
    {fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, VISIBLE 1 2 3, KTHXBYE",
        [{visible, [{numbr, 1},{numbr, 2},{numbr, 3}]}]},
    {"condition ya", fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, O RLY? , YA RLY, VISIBLE 1, OIC , KTHXBYE",
        [{condition, {[{visible, [{numbr,1}]}], [], []}}]},
% Spec says YA needed
%    {"condition no", fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
%        "HAI, O RLY? , NO WAI, VISIBLE 1, OIC , KTHXBYE",
%        [{condition, {[], [{visible, [{numbr,1}]}], []}}]},
    {"condition mebbe1", fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, O RLY?, YA RLY, MEBBE WIN, VISIBLE 1, OIC , KTHXBYE",
        [{condition, {[], [], [
            {{troof, win},[{visible, [{numbr,1}]}]}
            ]}}]},
    {"condition mebbe2", fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, O RLY?, YA RLY, MEBBE WIN, VISIBLE 1, MEBBE FAIL, VISIBLE 2, OIC , KTHXBYE",
        [{condition, {[], [], [
            {{troof, win},[{visible, [{numbr,1}]}]},
            {{troof, fail},[{visible, [{numbr,2}]}]}
            ]}}]},
    {"condition full", fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, O RLY? , YA RLY, 1, MEBBE WIN, 2, MEBBE FAIL, 3, NO WAI, 4, OIC , KTHXBYE",
        [{condition, {[{expression,{numbr,1}}], [{expression,{numbr,4}}], [
            {{troof, win},[{expression,{numbr,2}}]},
            {{troof, fail},[{expression,{numbr,3}}]}
            ]}}]},
    {fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, abc IS NOW A TROOF, KTHXBYE",
        [{cast_inplace, {identifier, "abc"}, {type, troof}}]},
    {fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, MAEK abc TROOF, KTHXBYE",
        [{expression, {cast, {identifier, "abc"}, {type, troof}}}]},
    {fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, MAEK abc A TROOF, KTHXBYE",
        [{expression, {cast, {identifier, "abc"}, {type, troof}}}]},
    {fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, I HAS A abc ITZ MAEK SUM OF 1 AN 2 A YARN, KTHXBYE",
        [{assignment_new, "abc", {cast, {binary_math_op, kw_sum, {numbr, 1}, {numbr, 2}}, {type, yarn}} } ]},
    {fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, NOT WIN, KTHXBYE",
        [{expression, {unary_op, kw_not, {troof, win}}}]},
    {fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI, IM IN YR loop, WIN, IM OUTTA YR loop, KTHXBYE",
        [{loop, [{expression, {troof, win}}]}]},
    {fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI , , KTHXBYE",
        []},
    {fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI , GIMMEH ind IN MAH bukkit , KTHXBYE",
        [{gimmeh, {bukkit_selector, {identifier, "bukkit"}, [{identifier, "ind"}]}}]},
    {"case", fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI , WTF?, OMG 1, 2, OMG 3, 4, OIC, KTHXBYE",
        [{switch, [
            {{numbr,1}, [{expression, {numbr,2}}]},
            {{numbr,3}, [{expression, {numbr,4}}]}
            ]}]},
    {"case fall", fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
        "HAI , WTF?, OMG 1, OMG 3, 4, OIC, KTHXBYE",
        [{switch, [
            {{numbr,1}, []},
            {{numbr,3}, [{expression, {numbr,4}}]}
            ]}]},
    {"case catchall", fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
		"HAI , WTF?, OMG 1, 2, OMGWTF, 4, OIC, KTHXBYE",
        [{switch, [
			{{numbr,1}, [{expression, {numbr,2}}]},
            {catchall, [{expression, {numbr,4}}]}
            ]}]},
	{"case gtfo", fun(A) when is_list(A) -> parse(scanner:scan(A)) end,
       "HAI, 2, WTF?, OMG 2, 100, GTFO, OMG 1, 200, OIC, KTHXBYE",
        [{expression, {numbr,2}},
		{switch, [
			{{numbr,2}, [{expression, {numbr,100}}, {gtfo}]},
            {{numbr,1}, [{expression, {numbr,200}}]}
            ]}]}
    ].

test() -> tester:test(test_set()).
